using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using GameFramework;
using LS;
using UnityEditor;
using UnityGameFramework.Editor;
using Type = System.Type;

namespace LS.Editor.VisualScripting
{
    public class EventUnitGenerator
    {
        private static readonly string VisualScriptingTemplatePath = "Packages/com.lancerstudio.lsframework/Editor/Assets/CodeTemplate/VisualScripingEventUnitTemplate.txt";
        private static readonly string OutputPackagePath = "Packages/com.lancerstudio.lsframework/VisualScripting/Unit/Event";
        private static readonly string OutputAssetPath = "Assets/LSRuntime/Scripts/VisualScripting/Unit";
        private static readonly Regex EndWithNumberRegex = new Regex(@"\d+$");
        private static readonly Regex NameRegex = new Regex(@"^[A-Z][A-Za-z0-9_]*$");
        private static TypeSearch s_TypeSearch = new TypeSearch();
        private static void EventUnitCodeGenerator(StringBuilder codeContent, Type type)
        {
            // string dataTableName = (string)userData;
            string nameSpace = type.Namespace;
            string name = type.Name;
            if (name.EndsWith("EventArgs"))
            {
                name = name.Substring(0, name.Length - "EventArgs".Length);
            }
            // codeContent.Replace("__UNIT_NAME_SPACE__", nameSpace);
            // codeContent.Replace("__UNIT_CLASS_NAME__", name);
            // codeContent.Replace("__EVENT_ARGS_TYPE_NAME__", type.FullName);
            // codeContent.Replace("__UNIT_PROPERTIES__", GenerateDataTableProperties.GetValue(0, 1) + "。");
            // codeContent.Replace("__UNIT_Functions__", GenerateFunctions(dataTableProcessor));
        }

        public void GenerateEventUnit(string[] assemblys, string targetDirectory = null)
        {
            s_TypeSearch.Clear();
            s_TypeSearch.AddAssemblyName(assemblys);
            if (string.IsNullOrEmpty(targetDirectory))
            {
                targetDirectory = OutputAssetPath;
            }

            var baseType = typeof(GameFrameworkEventArgs);
            s_TypeSearch.Search(t =>
            {
                return t.IsAssignableFrom(baseType) && !t.IsAbstract;
            });
        }
        
        public void GenerateEventUnit(Assembly assembly, string targetDirectory = null)
        {
            // assembly.GetExportedTypes()
        }
        
        public void GenerateEventUnit(Type baseType, string targetDirectory = null)
        {
            
        }
        
        private StringBuilder ReadTemplate(string templateName)
        {
            TextAsset template = AssetDatabase.LoadAssetAtPath<TextAsset>(templateName);
            StringBuilder builder = new StringBuilder(template.text);
            return builder;
        }
        
        private static string GenerateProperties(Type type)
        {
            StringBuilder stringBuilder = new StringBuilder();
            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            for (int i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                string fieldName = field.Name;
                fieldName = char.ToUpper(fieldName[0]) + fieldName.Substring(1);
                stringBuilder.AppendFormat("        [DoNotSerialize] public ValueOutput {0} {{ get; private set; }}",
                    fieldName);
                stringBuilder.AppendLine();
            }

            for (int i = 0; i < properties.Length; i++)
            {
                 var property = properties[i];
                 string propertyName = property.Name;
                 propertyName = char.ToUpper(propertyName[0]) + propertyName.Substring(1);
                 stringBuilder.AppendFormat("        [DoNotSerialize] public ValueOutput {0} {{ get; private set; }}",
                     propertyName);
                 stringBuilder.AppendLine();
            }
            return stringBuilder.ToString();
        }

        private static string GenerateFunctions(Type type)
        {
            StringBuilder stringBuilder = new StringBuilder();
            var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            stringBuilder.Append("        protected override void Definition()").AppendLine();
            stringBuilder.Append("        {").AppendLine();
            stringBuilder.Append("            base.Definition();").AppendLine();
            for (int i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                string fieldName = field.Name;
                if(fieldName.ToLower() == "id") continue;
                string targetPropertyName =  char.ToUpper(fieldName[0]) + fieldName.Substring(1);
                stringBuilder.AppendFormat("            {0} = ValueOutPut<{1}>(nameof({0}))", targetPropertyName, field.FieldType.FullName).AppendLine();
            }

            for (int i = 0; i < properties.Length; i++)
            {
                var property = properties[i];
                string propertyName = property.Name;
                if(propertyName.ToLower() == "id") continue;
                string targetPropertyName = char.ToUpper(propertyName[0]) + propertyName.Substring(1);
                
                stringBuilder.AppendFormat("            {0} = ValueOutPut<{1}>(nameof({0}))", targetPropertyName, property.PropertyType.FullName).AppendLine();
            }
            stringBuilder.Append("        }")
                .AppendLine()
                .AppendLine();
            
            stringBuilder.Append("        protected override void AssignArguments(Flow flow, OpenUIFormDependencyAssetEventArgs args)").AppendLine();
            stringBuilder.Append("        {").AppendLine();
            stringBuilder.Append("            base.AssignArguments(flow, args);").AppendLine();
            for (int i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                string fieldName = field.Name;
                if(fieldName.ToLower() == "id") continue;
                string targetPropertyName =  char.ToUpper(fieldName[0]) + fieldName.Substring(1);
                stringBuilder.AppendFormat("            flow.SetValue({0}, args.{1});", targetPropertyName, fieldName).AppendLine();
            }

            for (int i = 0; i < properties.Length; i++)
            {
                var property = properties[i];
                string propertyName = property.Name;
                if(propertyName.ToLower() == "id") continue;
                string targetPropertyName =  char.ToUpper(propertyName[0]) + propertyName.Substring(1);
                stringBuilder.AppendFormat("            flow.SetValue({0}, args.{1});", propertyName, targetPropertyName).AppendLine();
            }
            stringBuilder.Append("        }").AppendLine();
            return stringBuilder.ToString();
        }
    }
}